/**
 * 第1节
 * 本节的目的是迅速的实现一个最精简的语言的功能，让你了解一门计算机语言的骨架。
 *
 * 知识点：
 * 1.递归下降的方法做词法分析；
 * 2.语义分析中的引用消解（找到函数的定义）；
 * 3.通过遍历AST的方法，执行程序。
 *
 * 本节采用的语法规则是极其精简的，只能定义函数和调用函数。定义函数的时候，还不能有参数。
 *
 * EBNF规则：
 * prog = (functionDecl | functionCall)*
 * functionDecl: "function" Identifier "(" ")"  functionBody
 * functionBody : "{" functionCall* "}"
 * functionCall : Identifier "(" parameterList? ")"
 * parameterList : StringLiteral ("," StringLiteral)*
 *
 * 其他：
 * 系统调用以nl.开始
 * functionCall.name.startsWith("nl.")
 *
 * 例子中的两个Token数组，需要手工切换后tsc编译，再运行
 * 运行：
 * cargo build
 *
 */

//#[macro_use]
//extern crate lazy_static;

mod mynl;

use mynl::nast::Prog;
use mynl::nscanner::Token;
use mynl::nscanner::TokenKind;
use mynl::nscanner::Tokenizer;
use mynl::nparser::Parser;
use mynl::nsemantic::RefResolver;
use mynl::nintepretor::Intepretor;
use mynl::nast::IAstNode;
use mynl::nast::IAstVisitor;

/////////////////////////////////////////////////////////////////////////
// 主程序

fn compile_and_run(token_array:Vec<Token>) {
	//词法分析
	println!("\n程序所使用的Token:");
	for x in &*token_array
	{
		println!("{}",x);
	}
	let tokenizer = Tokenizer::new(token_array);

	//语法分析
	let mut prog: &mut Prog = &mut Parser::new(tokenizer).parse_prog();
	prog = prog;
	println!("\n语法分析后的AST，注意自定义函数的调用未被消解:");
	prog.dump(&String::from(""));

	//语义分析
	prog = RefResolver::visit_prog(prog);
	println!("\n语义分析后的AST，注意自定义函数的调用已被消解:");
	prog.dump(&String::from(""));

	//运行程序
	println!("\n运行当前的程序:");
	let ret_val = Intepretor::new().visit_prog(prog);
	if ret_val.is_none() {
		println!("程序返回值：None\n");
	} else{
		println!("程序返回值：{}\n", ret_val.unwrap());
	}
}

fn main() {
	// 第1个Token数组，代表了下面这段程序做完词法分析后的结果：
	/*
	function sayHello(){
		println("Hello World!");
	}
	sayHello();
	*/
	let  _token_array_say_hello: Vec<Token> = vec![
		Token{kind: TokenKind::Keyword, text: String::from("function")},
		Token{kind: TokenKind::Identifier, text: String::from("sayHello")},
		Token{kind: TokenKind::Seperator, text: String::from("(")},
		Token{kind: TokenKind::Seperator, text: String::from(")")},
		Token{kind: TokenKind::Seperator, text: String::from("{")},
		Token{kind: TokenKind::Identifier, text: String::from("nl.println")},
		Token{kind: TokenKind::Seperator, text: String::from("(")},
		Token{kind: TokenKind::StringLiteral, text: String::from("Hello World!")},
		Token{kind: TokenKind::Seperator, text: String::from(")")},
		Token{kind: TokenKind::Seperator, text: String::from(";")},
		Token{kind: TokenKind::Seperator, text: String::from("}")},
		Token{kind: TokenKind::Identifier, text: String::from("sayHello")},
		Token{kind: TokenKind::Seperator, text: String::from("(")},
		Token{kind: TokenKind::Seperator, text: String::from(")")},
		Token{kind: TokenKind::Seperator, text: String::from(";")},
		Token{kind: TokenKind::EOF, text: String::from("")},
		];
	
	// 第2个Token数组，代表了下面这段程序做完词法分析后的结果：
	/*
	function foo(){
		println("in foo...");
	}
	function bar(){
		println("in bar...");
		foo();
	}
	bar();
	*/
	let _token_array_foobar: Vec<Token> = vec![
		Token{kind:TokenKind::Keyword, text:String::from("function")},
		Token{kind:TokenKind::Identifier, text:String::from("foo")},
		Token{kind:TokenKind::Seperator, text:String::from("(")},
		Token{kind:TokenKind::Seperator, text:String::from(")")},
		Token{kind:TokenKind::Seperator, text:String::from("{")},
		Token{kind:TokenKind::Identifier, text:String::from("nl.println")},
		Token{kind:TokenKind::Seperator, text:String::from("(")},
		Token{kind:TokenKind::StringLiteral, text:String::from("in foo...")},
		Token{kind:TokenKind::Seperator, text:String::from(")")},
		Token{kind:TokenKind::Seperator, text:String::from(";")},
		Token{kind:TokenKind::Seperator, text:String::from("}")},
		Token{kind:TokenKind::Keyword, text:String::from("function")},
		Token{kind:TokenKind::Identifier, text:String::from("bar")},
		Token{kind:TokenKind::Seperator, text:String::from("(")},
		Token{kind:TokenKind::Seperator, text:String::from(")")},
		Token{kind:TokenKind::Seperator, text:String::from("{")},
		Token{kind:TokenKind::Identifier, text:String::from("nl.println")},
		Token{kind:TokenKind::Seperator, text:String::from("(")},
		Token{kind:TokenKind::StringLiteral, text:String::from("in bar...")},
		Token{kind:TokenKind::Seperator, text:String::from(")")},
		Token{kind:TokenKind::Seperator, text:String::from(";")},
		Token{kind:TokenKind::Identifier, text:String::from("foo")},
		Token{kind:TokenKind::Seperator, text:String::from("(")},
		Token{kind:TokenKind::Seperator, text:String::from(")")},
		Token{kind:TokenKind::Seperator, text:String::from(";")},
		Token{kind:TokenKind::Seperator, text:String::from("}")},
		Token{kind:TokenKind::Identifier, text:String::from("bar")},
		Token{kind:TokenKind::Seperator, text:String::from("(")},
		Token{kind:TokenKind::Seperator, text:String::from(")")},
		Token{kind:TokenKind::Seperator, text:String::from(";")},
		Token{kind:TokenKind::EOF, text:String::from("")},
		];
		
	//运行示例
	//compile_and_run(_token_array_say_hello);
	compile_and_run(_token_array_foobar);
}
